﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Eventing.Reader;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TM.Common.Extensions;
using TM.Data;
using TM.Data.Contracts;
using TM.Data.ViewModels;
using TM.Data.ViewModels.VmMapper;
using TM.Model;
using TM.Plugable;

namespace TM.ProjectKeeper
{
    public partial class ProjectEditorControl : UserControl, IProjectEditor
    {
        private bool _isDirty;
        
        private Dictionary<string, string> menuText;
 
        public ProjectEditorControl()
        {
            InitializeComponent();
            InitializeMenuText();
            this.ganttView.Dock = DockStyle.Fill;
        }

        private void InitializeMenuText()
        {
            menuText = new Dictionary<string, string>()
                           {
                               {"&Insert Task", "&1. Thêm task mới"}, 
                               {"&Add sub-task for", "&2. Thêm task nhỏ cho ''"}, 
                               {"&Delete Task", "&3. Xóa task đang chọn"}, 
                               {"Task &Information", "&4. Xem thông tin task đang chọn"}, 
                               {"&Indent Task", "&5. Chuyển thành task nhỏ"}, 
                               {"&Outdent Task", "&6. Chuyển thành task lớn"}, 
                               {"&Hide sub-items", "&7. Ẩn các task nhỏ"}, 
                               {"&Show sub-items", "&8. Hiển thị các task nhỏ"}, 
                           };
        }

        #region Implementation of IProjectEditor

        public event ProjectDataIsChangedHandler ProjectDataIsChanged;

        public IVmMapper VmMapper { get; private set; }
        public IUnitOfWork UoW { get; private set; }
        public bool IsDataLoaded { get; private set; }
        public bool IsDirty
        {
            get { return _isDirty; }
            private set
            {
                if (_isDirty != value)
                {
                    InvokeDataChanged(value);
                }
                _isDirty = value;
            }
        }

        public object Session { get; private set; }
        public Guid ProjectId { get; private set; }

        public void SetIoC(IIoCParams ioCParams, IVmMapper vmMapper)
        {
            VmMapper = vmMapper;
            UoW = ioCParams.UnitOfWork;
        }

        public void LoadProjectInformation(Guid projectId)
        {
            ProjectId = projectId;

            ganttView.ContextMenuInitializing += new Infragistics.Win.UltraWinGanttView.ContextMenuInitializingHandler(ganttView_ContextMenuInitializing);

            var result = VmMapper.ExtractFromDboAsDataSet(false, projectId);
            Session = result;

            if (result != null && result.Projects.Count > 0)
            {
                var ds = result.Projects[0];

                this.calendarInfo.DataBindingsForTasks.BindingContextControl = this.Parent;
                this.calendarInfo.DataBindingsForProjects.BindingContextControl = this.Parent;

                //  Set the DataBinding members for Projects 
                this.calendarInfo.DataBindingsForProjects.SetDataBinding(result.ProjectsDataSet, "Projects");
                this.calendarInfo.DataBindingsForProjects.IdMember = ds.IDColumn;
                this.calendarInfo.DataBindingsForProjects.KeyMember = "ProjectKey";
                this.calendarInfo.DataBindingsForProjects.NameMember = ds.NameColumn;
                this.calendarInfo.DataBindingsForProjects.StartDateMember = ds.StartDateColumn;

                //  Set the DataBinding members for Tasks
                this.calendarInfo.DataBindingsForTasks.SetDataBinding(result.ProjectsDataSet, "Tasks");
                this.calendarInfo.DataBindingsForTasks.NameMember = ds.ProjectTaskFields.NameColumn;
                this.calendarInfo.DataBindingsForTasks.DurationMember = ds.ProjectTaskFields.DurationColumn;
                this.calendarInfo.DataBindingsForTasks.StartDateTimeMember = ds.ProjectTaskFields.StartDateColumn;
                this.calendarInfo.DataBindingsForTasks.IdMember = ds.ProjectTaskFields.IDColumn;
                this.calendarInfo.DataBindingsForTasks.ProjectKeyMember = "ProjectKey";
                this.calendarInfo.DataBindingsForTasks.ParentTaskIdMember = ds.ProjectTaskFields.ParentIDColumn;

                this.calendarInfo.DataBindingsForTasks.ConstraintMember = ds.ProjectTaskFields.ConstraintColumn;
                this.calendarInfo.DataBindingsForTasks.PercentCompleteMember = ds.ProjectTaskFields.PercentCompletedColumn;

                // All other properties
                this.calendarInfo.DataBindingsForTasks.AllPropertiesMember = "AllProperties";

                //  Since we are showing a task that belongs to an explicitly defined
                //  project (i.e., not the UnassignedProject), assign that project to
                //  the control's Project property so the control knows to display that project.
                this.ganttView.CalendarInfo = this.calendarInfo;
                this.ganttView.Project = this.ganttView.CalendarInfo.Projects[1];
                var c = this.ganttView.Project.Tasks.Count;
                this.ganttView.Refresh();
                this.ganttView.Update();
            }
            result.ProjectsDataSet.Tables["Tasks"].TableNewRow += new DataTableNewRowEventHandler(ProjectEditorControl_TableNewRow);
            result.ProjectsDataSet.Tables["Tasks"].RowDeleted += new DataRowChangeEventHandler(ProjectEditorControl_RowDeleted);
            result.ProjectsDataSet.Tables["Tasks"].RowChanged += new DataRowChangeEventHandler(ProjectEditorControl_RowChanged);
            IsDataLoaded = true;
        }

        void ganttView_ContextMenuInitializing(object sender, Infragistics.Win.UltraWinGanttView.ContextMenuInitializingEventArgs e)
        {
            var menuItems = e.DefaultContextMenu.MenuItems;
            var contextMenu = e.ContextMenu;
            var task = e.Task;
            var area = e.Area;
            
            //menuItems.Clear();
            List<string> mnus = new List<string>();
            foreach (MenuItem menuItem in menuItems)
            {
                if (string.IsNullOrEmpty(menuItem.Text)) continue;
                if (!menuText.Keys.Contains(menuItem.Text) && !menuItem.Text.Contains("Add sub-task for")) continue;

                if (menuItem.Text.Contains("Add sub-task for"))
                {
                    var taskName = menuItem.Text.Substring(menuItem.Text.IndexOf('\'')).Trim('\'');
                    menuItem.Text = string.Format("{0} '{1}'", menuText["&Add sub-task for"], taskName);
                }
                else
                {
                    menuItem.Text = menuText[menuItem.Text];    
                }
            }

            var loc = e.Location;
        }

        void ProjectEditorControl_RowChanged(object sender, DataRowChangeEventArgs e)
        {
            this.IsDirty = true;
        }

        void ProjectEditorControl_RowDeleted(object sender, DataRowChangeEventArgs e)
        {
            this.IsDirty = true;
        }

        void ProjectEditorControl_TableNewRow(object sender, DataTableNewRowEventArgs e)
        {
            this.IsDirty = true;
        }

        public void RemoveCurrentTask()
        {
            throw new NotImplementedException();
        }

        public void CreateNewTask()
        {
            throw new NotImplementedException();
        }

        public void Save()
        {
            var tasks = VmMapper.ExtractTaskDboFormSession(Session as Session);
            if(UoW.Task.Update(tasks))
            {
                this.IsDirty = false;
            }
        }

        public void Release()
        {
            throw new NotImplementedException();
        }

        #endregion

        private void InvokeDataChanged(bool isDirty)
        {
            if (ProjectDataIsChanged != null)
            {
                ProjectDataIsChanged.Invoke(this, isDirty);
            }
        }
    }
}
